﻿package kliment.geom.color {
	import kliment.math.Calc;
	
	/**
	* ...
	* @author Kliment
	*/
	public class RGBColor  extends ColorAbstract {
		private const WHITE:int = 255;
		
		public var rawR:Number = 0;
        public var rawB:Number = 0;
        public var rawG:Number = 0;
        
		public function RGBColor(host:Color = null) {
			super(host);
		}
		
		public function get r():Number { return rawR * WHITE }
		public function get g():Number { return rawG * WHITE }
		public function get b():Number { return rawB * WHITE }
		
		public function setValue(r:Number, g:Number, b:Number, update:Boolean = true):void {
			setRawValue(r / WHITE, g / WHITE, b / WHITE, update);
		}
		
		public function setRawValue(r:Number, g:Number, b:Number, update:Boolean = true):void {
			if (rawR == r && rawG == g && rawB == b)
				return;
			rawR = Calc.inInterval(MIN_RAW, MAX_RAW, r);
			rawG = Calc.inInterval(MIN_RAW, MAX_RAW, g);
			rawB = Calc.inInterval(MIN_RAW, MAX_RAW, b);
			
			if (color && update)
				color.valueChanged(Color.RGB);
		}
		
		public function toString():String {
			return "[RGBColor r=" + r + " g=" + g + " b=" + b + "]";
		}
		
		public function clone():RGBColor {
			var result:RGBColor = new RGBColor();
			result.setRawValue(rawR, rawG, rawB, false);
			return result;
		}
		
		public function toHSV(hsv:HSVColor = null):HSVColor { return converToHSV(this, hsv) }
		static public function converToHSV(rgb:RGBColor, hsv:HSVColor = null):HSVColor {
			if (!hsv) hsv = new HSVColor();
			var r:Number = rgb.rawR; 
			var g:Number = rgb.rawG;
			var b:Number = rgb.rawB;
			
			var min:Number = Math.min(r, g, b); 
			var max:Number = Math.max(r, g, b);
			var delta:Number = max - min;
			var h:Number; 
			var s:Number;
			switch (max) {
				case min: h = 0; break;
				case r: 
						h = 60 * ( g - b ) / delta; 
						if ( g < b ) { 
							h += 360; 
						} 
				break;
				case g: h = ( 60 * ( b - r ) / delta ) + 120; break;
				case b: h = ( 60 * ( r - g ) / delta ) + 240; break;
			}
			s = ( max === 0 ) ? 0 : 1 - ( min / max );
			hsv.setValue(h, s * 100, max * 100, false);
			return hsv;
		}
		
		public function toXYZ(xyz:XYZColor = null):XYZColor { return converToXYZ(this, xyz) }
		static public function converToXYZ(rgb:RGBColor, xyz:XYZColor = null):XYZColor {
			if (!xyz) xyz = new XYZColor();
			
			var r:Number = rgb.rawR;
			var g:Number = rgb.rawG;
			var b:Number = rgb.rawB;
			r = r > .04045 ? (Math.pow((r + .055) / 1.055, 2.4)) : (r / 12.92);
			g = g > .04045 ? (Math.pow((g + .055) / 1.055, 2.4)) : (g / 12.92);
			b = b > .04045 ? (Math.pow((b + .055) / 1.055, 2.4)) : (b / 12.92);
			var x:Number = (.4124 * r + 0.3576 * g + .1805 * b) * 100 / 95.047;
			var y:Number = .2126 * r + 0.7152 * g + .0722 * b;
			var z:Number = (.0193 * r + 0.1192 * g + .9505 * b) * 100 / 108.883;
			xyz.setRawValue(x, y, z, false);
			return xyz;
		}
		
		public function toCMYK(cmyk:CMYKColor = null):CMYKColor { return converToCMYK(this, cmyk) }
		static public function converToCMYK(rgb:RGBColor, cmyk:CMYKColor = null):CMYKColor {
			if (!cmyk) cmyk = new CMYKColor();
			
			var r:Number = 1 - rgb.rawR;
			var g:Number = 1 - rgb.rawG;
			var b:Number = 1 - rgb.rawB;
			
			var k:Number = Math.min(r, g, b);
			
			var c:Number = (r - k) / ( 1 - k);
			var m:Number = (g - k) / ( 1 - k);
			var y:Number = (b - k) / ( 1 - k);
			
			cmyk.setRawValue(c, m, y, k, false);
			return cmyk;
		}
	}
}